package com.bcinfo.iccard.admin.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Random;

import javax.imageio.ImageIO;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class DataMatrixUtil {

	private final static Logger          _log      = Logger.getLogger(DataMatrixUtil.class); 
	private final static int DEFAULT_WIDTH = 200;
	private final static int DEFAULT_HEIGHT = 200;

	@SuppressWarnings("unchecked")
	public static void decode(String imgPath) {
		try {
			File file = new File(imgPath);
			BufferedImage image;
			try {
				image = ImageIO.read(file);
				if (image == null) {
					if(_log.isInfoEnabled())
					{
						_log.info("Could not decode image");
					}
				}
				LuminanceSource source = new BufferedImageLuminanceSource(image);
				BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(
						source));
				Result result;
				@SuppressWarnings("rawtypes")
				Hashtable hints = new Hashtable();
				hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
				result = new MultiFormatReader().decode(bitmap, hints);
				String resultStr = result.getText();
				
				if(_log.isInfoEnabled())
				{
					_log.info(resultStr);
				}

			} catch (IOException e) {
				_log.error(ExceptionUtils.getStackTrace(e));
			} catch (ReaderException e) {
				_log.error(ExceptionUtils.getStackTrace(e));
			}
		} catch (Exception e) {
			_log.error(ExceptionUtils.getStackTrace(e));
		}
	}
	
	private static final MatrixToLogoImageConfig DEFAULT_CONFIG = new MatrixToLogoImageConfig();

	/**
	 * 根据内容生成二维码数据
	 * 
	 * @param content
	 *            二维码文字内容[为了信息安全性，一般都要先进行数据加密]
	 * @param width
	 *            二维码照片宽度
	 * @param height
	 *            二维码照片高度
	 * @return
	 */
	public static BitMatrix encode(String content, int width, int height) {
		if(width == 0){
			width = DEFAULT_WIDTH;
		}
		if(height == 0){
			height = DEFAULT_HEIGHT;
		}
		Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
		// 设置字符编码
		hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
		// 指定纠错等级
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		BitMatrix matrix = null;
		try {
			matrix = new MultiFormatWriter().encode(content,
					BarcodeFormat.QR_CODE, width, height, hints);
		} catch (WriterException e) {
			e.printStackTrace();
		}
		return matrix;
	}

	/**
	 * 写入二维码、以及将照片logo写入二维码中
	 * 
	 * @param matrix
	 *            要写入的二维码
	 * @param format
	 *            二维码照片格式
	 * @param imagePath
	 *            二维码照片保存路径
	 * @param logoPath
	 *            logo路径
	 * @throws IOException
	 */
	public static void writeToFile(BitMatrix matrix, String format,
			String imagePath, String logoPath) throws IOException {
		MatrixToImageWriter.writeToFile(matrix, format, new File(imagePath),
				new MatrixToImageConfig());

		// 添加logo图片, 此处一定需要重新进行读取，而不能直接使用二维码的BufferedImage 对象
		BufferedImage img = ImageIO.read(new File(imagePath));
		overlapImage(img, format, imagePath, logoPath,
				DEFAULT_CONFIG);
	}
	
	/**
     * 写入二维码
     * 
     * @param matrix
     *            要写入的二维码
     * @param format
     *            二维码照片格式
     * @param imagePath
     *            二维码照片保存路径
     * @throws IOException
     */
	public static void writeToFile(BitMatrix matrix, String format,
            String imagePath) throws IOException {
        MatrixToImageWriter.writeToFile(matrix, format, new File(imagePath),
                new MatrixToImageConfig());

        // 添加logo图片, 此处一定需要重新进行读取，而不能直接使用二维码的BufferedImage 对象
        ImageIO.read(new File(imagePath));
    }


	/**
	 * 写入二维码、以及将照片logo写入二维码中
	 * 
	 * @param matrix
	 *            要写入的二维码
	 * @param format
	 *            二维码照片格式
	 * @param imagePath
	 *            二维码照片保存路径
	 * @param logoPath
	 *            logo路径
	 * @param logoConfig
	 *            logo配置对象
	 * @throws IOException
	 */
	public static void writeToFile(BitMatrix matrix, String format,
			String imagePath, String logoPath,
			MatrixToLogoImageConfig logoConfig) throws IOException {
		MatrixToImageWriter.writeToFile(matrix, format, new File(imagePath),
				new MatrixToImageConfig());

		// 添加logo图片, 此处一定需要重新进行读取，而不能直接使用二维码的BufferedImage 对象
		BufferedImage img = ImageIO.read(new File(imagePath));
		overlapImage(img, format, imagePath, logoPath,
				logoConfig);
	}

	/**
	 * 将照片logo添加到二维码中间
	 * 
	 * @param image
	 *            生成的二维码照片对象
	 * @param imagePath
	 *            照片保存路径
	 * @param logoPath
	 *            logo照片路径
	 * @param formate
	 *            照片格式
	 */
	public static void overlapImage(BufferedImage image, String formate,
			String imagePath, String logoPath,
			MatrixToLogoImageConfig logoConfig) {
		try {
			BufferedImage logo = ImageIO.read(new File(logoPath));
			Graphics2D g = image.createGraphics();
			// 考虑到logo照片贴到二维码中，建议大小不要超过二维码的1/5;
			int width = image.getWidth() / logoConfig.getLogoPart();
			int height = image.getHeight() / logoConfig.getLogoPart();
			// logo起始位置，此目的是为logo居中显示
			int x = (image.getWidth() - width) / 2;
			int y = (image.getHeight() - height) / 2;
			// 绘制图
			g.drawImage(logo, x, y, width, height, null);

			// 给logo画边框
			// 构造一个具有指定线条宽度以及 cap 和 join 风格的默认值的实心 BasicStroke
			g.setStroke(new BasicStroke(logoConfig.getBorder()));
			g.setColor(logoConfig.getBorderColor());
			g.drawRect(x, y, width, height);

			g.dispose();
			// 写入logo照片到二维码
			ImageIO.write(image, formate, new File(imagePath));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String randomNumber(){
	    int number=new Random().nextInt(9999);
	    String str="";
	    if(number<10){
	        str = "000"+number; 
	    }else if(number<100){
	        str = "00"+number; 
	    }else if(number<1000){
	        str = "0"+number; 
	    }else{
	        str = ""+number;
	    }
	    return str;
	}
	
	public static void main(String[] args) {
		//decode("d:\\imgQRCode.png");
		
		try {
			int width = 200;
			int height = 200;
			String content = "http://www.taobao.com";
			BitMatrix matrix = encode(content, width, height);
//			MatrixToLogoImageConfig logoConfig = new MatrixToLogoImageConfig(Color.BLUE, 4);
//			writeToFile(matrix, "jpg", "D:\\imgQRCode.png", "D:\\logo.png", logoConfig);
			writeToFile(matrix, "jpg", "D:\\qrimg\\imgQRCode.png");
			System.out.println("生成二维码结束！");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}



class MatrixToLogoImageConfig {
	// logo默认边框颜色
	public static final Color DEFAULT_BORDERCOLOR = Color.RED;
	// logo默认边框宽度
	public static final int DEFAULT_BORDER = 2;
	// logo大小默认为照片的1/5
	public static final int DEFAULT_LOGOPART = 5;

	private final int border = DEFAULT_BORDER;
	private final Color borderColor;
	private final int logoPart;

	/**
	 * Creates a default config with on color {@link #BLACK} and off color
	 * {@link #WHITE}, generating normal black-on-white barcodes.
	 */
	public MatrixToLogoImageConfig() {
		this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
	}

	public MatrixToLogoImageConfig(Color borderColor, int logoPart) {
		this.borderColor = borderColor;
		this.logoPart = logoPart;
	}

	public Color getBorderColor() {
		return borderColor;
	}

	public int getBorder() {
		return border;
	}

	public int getLogoPart() {
		return logoPart;
	}
}